const _ = require('lodash');
const { TABLE_NAME, knex } = require('../models');
const DbService = require('./db2');
const { logger, WORKER_CONTRACT_STATTUS } = require('../utils');
const BaseService = require('./base');
class ContractService extends BaseService {
  constructor() {
    super();
    this.dbService = new DbService(TABLE_NAME.contract);
  }

  async create(data) {
    const flowId = data?.FlowId;
    return this.dbService.insert({
      ...data,
      id: flowId,
    });
  }

  async filterByOrganizationId({ organizationId }) {
    const data = await this.dbService.selectAll();
    return data.map(item => {
      if (item.FlowApproverInfos) {
        item.FlowApproverInfos = JSON.parse(item.FlowApproverInfos);
      }
      return item;
    }).filter(item => item.FlowApproverInfos?.[0]?.ProxyOrganizationOpenId === organizationId);
  }


  // 回调状态更新
  async updateCallbackChangeStatus(flowId, data) {
    try {
      const getNewStatus = target => {
        const { FlowApproverInfos: oldFlowApproverInfo, ...oldRest } = target;
        // eslint-disable-next-line no-unused-vars
        const { FlowApproverInfo = [], ...newRest } = data;

        let mapKey = _.keyBy(FlowApproverInfo, 'recipientId');
        if (!mapKey) {
          mapKey = _.keyBy(FlowApproverInfo, 'RecipientId');
        }

        // 接口的recipientId, ReceiptId不一致
        const flowApproverInfo = (target && target.FlowApproverInfos) ? JSON.parse(target.FlowApproverInfos) : [];

      flowApproverInfo?.forEach(flow => {
        const { ApproveStatus, ApproveMessage = '' } = mapKey[flow.ReceiptId] || {};
        if (ApproveStatus) {
          flow.ApproveStatus = ApproveStatus;
          flow.ApproveMessage = ApproveMessage;
        }
      });

      const mixObj = {};
      Object.keys(oldRest).forEach((key) => {
        mixObj[key] = newRest[key] || oldRest[key];
        mixObj.FlowApproverInfos = JSON.stringify(flowApproverInfo);
      });

      logger.info({
        action: 'updateCallbackChangeStatus',
        data: {
          old: target,
          new: data,
          oldRest,
          newRest,
          FlowApproverInfo: flowApproverInfo,
          mixObj,
        },
      });

      return mixObj;
      // return {
      //   ...oldRest,
      //   ...newRest,
      //   FlowApproverInfos: JSON.stringify(flowApproverInfo),
      // };
      };


      const target = await this.dbService.getById(flowId);

      if (!target) return {};

      const updateStatus = getNewStatus(target);

      return await this.dbService.updateById(flowId, updateStatus);
    } catch (err) {
      logger.error({
        action: 'updateCallbackChangeStatus',
        ...data,
        errMessage: err.message,
      });
    }

    // 本地调试
    // const contractData = this.getContractData();
    // const target = contractData.find(contract => contract.FlowId === flowId);
    // const updateStatus = getNewStatus(target);
    // Object.assign(target, updateStatus);
    // jsonfile.writeFileSync(contractDataFilePath, contractData, { spaces: 2 });
    // return contractData;
  }

  async searchWithWorkers({ flowId, flowStatus, organizationId, flowName, offset, limit }) {
    const where = {
      [`${TABLE_NAME.contract}.organizationId`]: organizationId,
    };
    if (flowId) {
      where[`${TABLE_NAME.contract}.FlowId`] = flowId;
    }
    if (flowStatus) {
      where[`${TABLE_NAME.contract}.FlowStatus`] = flowStatus;
    }
    let result = knex.select(
      `${TABLE_NAME.contract}.id`,
      `${TABLE_NAME.contract}.FlowId`,
      `${TABLE_NAME.contract}.FlowName`,
      `${TABLE_NAME.contract}.FlowMessage`,
      `${TABLE_NAME.contract}.FlowStatus`,
      `${TABLE_NAME.contract}.FlowType`,
      `${TABLE_NAME.contract}.SignBeanTag`,
      `${TABLE_NAME.contract}.UserId`,
      `${TABLE_NAME.contract}.FlowApproverInfos`,
      `${TABLE_NAME.contract}.DeadLine`,
      `${TABLE_NAME.contract}.CustomData`,
      `${TABLE_NAME.contract}.CreateOn`,
      `${TABLE_NAME.contract}.contractStartTime`,
      `${TABLE_NAME.contract}.contractEndTime`,
      `${TABLE_NAME.worker}.id as workerId`,
      `${TABLE_NAME.worker}.name as workerName`,
      `${TABLE_NAME.worker}.mobile as workerMobile`,
      `${TABLE_NAME.worker}.gender as workerGender`,
      `${TABLE_NAME.worker}.age as workerAge`,
      `${TABLE_NAME.worker}.idcardNo as workerIdcardNo`,
      `${TABLE_NAME.worker}.status as workStatus`,
    ).from(TABLE_NAME.contract)
      .where(where);
    if (flowName) {
      result = result.whereILike(`${TABLE_NAME.contract}.FlowName`, `%${flowName}%`);
    }
    result = result
      .rightJoin(TABLE_NAME.workerSignRecord, `${TABLE_NAME.workerSignRecord}.contractId`, `${TABLE_NAME.contract}.id`)
      .leftJoin(TABLE_NAME.worker, `${TABLE_NAME.workerSignRecord}.workerId`, `${TABLE_NAME.worker}.id`)
      .limit(limit)
      .offset(offset);
    return result;
  }

  // 移动端
  // 1.移动端对合同状态做了处理,处理后为四种状态: 待签署/签署中/已签署/签署失败
  // 2. h5签署列表需根据签署人状态特殊处理下合同待签署和签署中的状态
  //    待签署-展示C端客户未签署的情况
  //    签署中-展示C端客户已签署 B端企业未签署情况
  async searchWithWorkersByMobile({ flowStatus, organizationId, offset, limit, workerId }) {
    let result = knex.select(
      `${TABLE_NAME.contract}.id`,
      `${TABLE_NAME.contract}.FlowId`,
      `${TABLE_NAME.contract}.FlowName`,
      `${TABLE_NAME.contract}.FlowMessage`,
      `${TABLE_NAME.contract}.FlowStatus`,
      `${TABLE_NAME.contract}.FlowType`,
      `${TABLE_NAME.contract}.SignBeanTag`,
      `${TABLE_NAME.contract}.UserId`,
      `${TABLE_NAME.contract}.FlowApproverInfos`,
      `${TABLE_NAME.contract}.DeadLine`,
      `${TABLE_NAME.contract}.CustomData`,
      `${TABLE_NAME.contract}.CreateOn`,
      `${TABLE_NAME.contract}.contractStartTime`,
      `${TABLE_NAME.contract}.contractEndTime`,
      `${TABLE_NAME.worker}.id as workerId`,
      `${TABLE_NAME.worker}.name as workerName`,
      `${TABLE_NAME.worker}.mobile as workerMobile`,
      `${TABLE_NAME.worker}.gender as workerGender`,
      `${TABLE_NAME.worker}.age as workerAge`,
      `${TABLE_NAME.worker}.idcardNo as workerIdcardNo`,
      `${TABLE_NAME.worker}.status as workStatus`,
    ).from(TABLE_NAME.contract)
      .where((builder) =>
        builder
          .whereIn(`${TABLE_NAME.contract}.FlowStatus`, WORKER_CONTRACT_STATTUS[flowStatus]), // 移动端状态筛选
      )
      .andWhere(function () {
        this.where(`${TABLE_NAME.contract}.organizationId`, organizationId),
        this.where(`${TABLE_NAME.worker}.id`, workerId);
      });

    result = result
      .join(TABLE_NAME.workerSignRecord, function () {
        this.on(`${TABLE_NAME.workerSignRecord}.contractId`, '=', `${TABLE_NAME.contract}.id`);
      })
      .join(TABLE_NAME.worker, function () {
        this.on(`${TABLE_NAME.workerSignRecord}.workerId`, '=', `${TABLE_NAME.worker}.id`);
      })
      .orderBy([
        { column: `${TABLE_NAME.contract}.CreateOn`, order: 'desc' },
      ])
      .limit(limit)
      .offset(offset);

    return result;
  }

  async searchWithTenants({ flowId, flowStatus, organizationId, flowName, offset, limit }) {
    const where = {
      [`${TABLE_NAME.contract}.organizationId`]: organizationId,
    };
    if (flowId) {
      where[`${TABLE_NAME.contract}.FlowId`] = flowId;
    }
    if (flowStatus) {
      where[`${TABLE_NAME.contract}.FlowStatus`] = flowStatus;
    }
    let result = knex.select(
      `${TABLE_NAME.contract}.id`,
      `${TABLE_NAME.contract}.FlowId`,
      `${TABLE_NAME.contract}.FlowName`,
      `${TABLE_NAME.contract}.FlowMessage`,
      `${TABLE_NAME.contract}.FlowStatus`,
      `${TABLE_NAME.contract}.FlowType`,
      `${TABLE_NAME.contract}.SignBeanTag`,
      `${TABLE_NAME.contract}.UserId`,
      `${TABLE_NAME.contract}.FlowApproverInfos`,
      `${TABLE_NAME.contract}.DeadLine`,
      `${TABLE_NAME.contract}.CustomData`,
      `${TABLE_NAME.contract}.CreateOn`,
      `${TABLE_NAME.contract}.contractStartTime`,
      `${TABLE_NAME.contract}.contractEndTime`,
      `${TABLE_NAME.tenant}.id as tenantId`,
      `${TABLE_NAME.tenant}.name as tenantName`,
      `${TABLE_NAME.tenant}.enterpriseOperator as enterpriseOperator`,
      `${TABLE_NAME.tenant}.latestFlowStatus as tenantFlowStatus`,
      `${TABLE_NAME.tenant}.contractEndDate as tenantContractEndDate`,
    ).from(TABLE_NAME.contract)
      .where(where);
    if (flowName) {
      result = result.whereILike(`${TABLE_NAME.contract}.FlowName`, `%${flowName}%`);
    }
    result = result
      .rightJoin(TABLE_NAME.tenantSignRecord, `${TABLE_NAME.tenantSignRecord}.contractId`, `${TABLE_NAME.contract}.id`)
      .leftJoin(TABLE_NAME.tenant, `${TABLE_NAME.tenantSignRecord}.tenantId`, `${TABLE_NAME.tenant}.id`)
      .limit(limit)
      .offset(offset);
    return result;
  }

  async countWithWorkers({ flowId, flowStatus, organizationId, flowName }) {
    const where = {
      [`${TABLE_NAME.contract}.organizationId`]: organizationId,
    };
    if (flowId) {
      where[`${TABLE_NAME.contract}.FlowId`] = flowId;
    }
    if (flowStatus) {
      where[`${TABLE_NAME.contract}.FlowStatus`] = flowStatus;
    }
    let result = this.dbService.knex(TABLE_NAME.contract)
      .where(where);
    if (flowName) {
      result = result.whereILike('FlowName', `%${flowName}%`);
    }
    result = result.rightJoin(TABLE_NAME.workerSignRecord, `${TABLE_NAME.workerSignRecord}.contractId`, `${TABLE_NAME.contract}.id`);
    const [{ count }] = await result.count({ count: '*' });
    return count;
  }

  async countWithWorkersByMobile({ flowStatus, organizationId, workerId }) {
    let result = this.dbService.knex(TABLE_NAME.contract).where((builder) =>
      builder
        .whereIn(`${TABLE_NAME.contract}.FlowStatus`, WORKER_CONTRACT_STATTUS[flowStatus]), // 移动端状态筛选
    )
      .andWhere(function () {
        this.where(`${TABLE_NAME.contract}.organizationId`, organizationId),
        this.where(`${TABLE_NAME.worker}.id`, workerId);
      });

    result = result
      .join(TABLE_NAME.workerSignRecord, function () {
        this.on(`${TABLE_NAME.workerSignRecord}.contractId`, '=', `${TABLE_NAME.contract}.id`);
      })
      .join(TABLE_NAME.worker, function () {
        this.on(`${TABLE_NAME.workerSignRecord}.workerId`, '=', `${TABLE_NAME.worker}.id`);
      });
    const [{ count }] = await result.count({ count: '*' });
    return count;
  }

  async countWithTenants({ flowId, flowStatus, organizationId, flowName }) {
    const where = {
      [`${TABLE_NAME.contract}.organizationId`]: organizationId,
    };
    if (flowId) {
      where[`${TABLE_NAME.contract}.FlowId`] = flowId;
    }
    if (flowStatus) {
      where[`${TABLE_NAME.contract}.FlowStatus`] = flowStatus;
    }
    let result = this.dbService.knex(TABLE_NAME.contract)
      .where(where);
    if (flowName) {
      result = result.whereILike('FlowName', `%${flowName}%`);
    }
    result = result.rightJoin(TABLE_NAME.tenantSignRecord, `${TABLE_NAME.tenantSignRecord}.contractId`, `${TABLE_NAME.contract}.id`);
    const [{ count }] = await result.count({ count: '*' });
    return count;
  }
}

module.exports = ContractService;
